home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2000 March / maximum-cd-2000-03.iso / Quake3 Game Source / Q3AGameSource.exe / Main / bg_misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  22.5 KB  |  1,004 lines

  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. // bg_misc.c -- both games misc functions, all completely stateless
  4.  
  5. #include "q_shared.h"
  6. #include "bg_public.h"
  7.  
  8. /*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
  9. DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION.
  10. The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
  11.  
  12. If an item is the target of another entity, it will not spawn in until fired.
  13.  
  14. An item fires all of its targets when it is picked up.  If the toucher can't carry it, the targets won't be fired.
  15.  
  16. "notfree" if set to 1, don't spawn in free for all games
  17. "notteam" if set to 1, don't spawn in team games
  18. "notsingle" if set to 1, don't spawn in single player games
  19. "wait"    override the default wait before respawning.  -1 = never respawn automatically, which can be used with targeted spawning.
  20. "random" random number of plus or minus seconds varied from the respawn time
  21. "count" override quantity or duration on most items.
  22. */
  23.  
  24. gitem_t    bg_itemlist[] = 
  25. {
  26.     {
  27.         NULL,
  28.         NULL,
  29.         { NULL,
  30.         NULL,
  31.         0, 0} ,
  32. /* icon */        NULL,
  33. /* pickup */    NULL,
  34.         0,
  35.         0,
  36.         0,
  37. /* precache */ "",
  38. /* sounds */ ""
  39.     },    // leave index 0 alone
  40.  
  41.     //
  42.     // ARMOR
  43.     //
  44.  
  45. /*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  46. */
  47.     {
  48.         "item_armor_shard", 
  49.         "sound/misc/ar1_pkup.wav",
  50.         { "models/powerups/armor/shard.md3", 
  51.         "models/powerups/armor/shard_sphere.md3",
  52.         0, 0} ,
  53. /* icon */        "icons/iconr_shard",
  54. /* pickup */    "Armor Shard",
  55.         5,
  56.         IT_ARMOR,
  57.         0,
  58. /* precache */ "",
  59. /* sounds */ ""
  60.     },
  61.  
  62. /*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  63. */
  64.     {
  65.         "item_armor_combat", 
  66.         "sound/misc/ar2_pkup.wav",
  67.         { "models/powerups/armor/armor_yel.md3",
  68.         0, 0, 0},
  69. /* icon */        "icons/iconr_yellow",
  70. /* pickup */    "Armor",
  71.         50,
  72.         IT_ARMOR,
  73.         0,
  74. /* precache */ "",
  75. /* sounds */ ""
  76.     },
  77.  
  78. /*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  79. */
  80.     {
  81.         "item_armor_body", 
  82.         "sound/misc/ar3_pkup.wav",
  83.         { "models/powerups/armor/armor_red.md3",
  84.         0, 0, 0},
  85. /* icon */        "icons/iconr_red",
  86. /* pickup */    "Heavy Armor",
  87.         100,
  88.         IT_ARMOR,
  89.         0,
  90. /* precache */ "",
  91. /* sounds */ ""
  92.     },
  93.  
  94.     //
  95.     // health
  96.     //
  97. /*QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  98. */
  99.     {
  100.         "item_health_small",
  101.         "sound/items/s_health.wav",
  102.         { "models/powerups/health/small_cross.md3", 
  103.         "models/powerups/health/small_sphere.md3", 
  104.         0, 0 },
  105. /* icon */        "icons/iconh_green",
  106. /* pickup */    "5 Health",
  107.         5,
  108.         IT_HEALTH,
  109.         0,
  110. /* precache */ "",
  111. /* sounds */ ""
  112.     },
  113.  
  114. /*QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  115. */
  116.     {
  117.         "item_health",
  118.         "sound/items/n_health.wav",
  119.         { "models/powerups/health/medium_cross.md3", 
  120.         "models/powerups/health/medium_sphere.md3", 
  121.         0, 0 },
  122. /* icon */        "icons/iconh_yellow",
  123. /* pickup */    "25 Health",
  124.         25,
  125.         IT_HEALTH,
  126.         0,
  127. /* precache */ "",
  128. /* sounds */ ""
  129.     },
  130.  
  131. /*QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  132. */
  133.     {
  134.         "item_health_large",
  135.         "sound/items/l_health.wav",
  136.         { "models/powerups/health/large_cross.md3", 
  137.         "models/powerups/health/large_sphere.md3", 
  138.         0, 0 },
  139. /* icon */        "icons/iconh_red",
  140. /* pickup */    "50 Health",
  141.         50,
  142.         IT_HEALTH,
  143.         0,
  144. /* precache */ "",
  145. /* sounds */ ""
  146.     },
  147.  
  148. /*QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  149. */
  150.     {
  151.         "item_health_mega",
  152.         "sound/items/m_health.wav",
  153.         { "models/powerups/health/mega_cross.md3", 
  154.         "models/powerups/health/mega_sphere.md3", 
  155.         0, 0 },
  156. /* icon */        "icons/iconh_mega",
  157. /* pickup */    "Mega Health",
  158.         100,
  159.         IT_HEALTH,
  160.         0,
  161. /* precache */ "",
  162. /* sounds */ ""
  163.     },
  164.  
  165.  
  166.     //
  167.     // WEAPONS 
  168.     //
  169.  
  170. /*QUAKED weapon_gauntlet (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  171. */
  172.     {
  173.         "weapon_gauntlet", 
  174.         "sound/misc/w_pkup.wav",
  175.         { "models/weapons2/gauntlet/gauntlet.md3",
  176.         0, 0, 0},
  177. /* icon */        "icons/iconw_gauntlet",
  178. /* pickup */    "Gauntlet",
  179.         0,
  180.         IT_WEAPON,
  181.         WP_GAUNTLET,
  182. /* precache */ "",
  183. /* sounds */ ""
  184.     },
  185.  
  186. /*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  187. */
  188.     {
  189.         "weapon_shotgun", 
  190.         "sound/misc/w_pkup.wav",
  191.         { "models/weapons2/shotgun/shotgun.md3", 
  192.         0, 0, 0},
  193. /* icon */        "icons/iconw_shotgun",
  194. /* pickup */    "Shotgun",
  195.         10,
  196.         IT_WEAPON,
  197.         WP_SHOTGUN,
  198. /* precache */ "",
  199. /* sounds */ ""
  200.     },
  201.  
  202. /*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  203. */
  204.     {
  205.         "weapon_machinegun", 
  206.         "sound/misc/w_pkup.wav",
  207.         { "models/weapons2/machinegun/machinegun.md3", 
  208.         0, 0, 0},
  209. /* icon */        "icons/iconw_machinegun",
  210. /* pickup */    "Machinegun",
  211.         40,
  212.         IT_WEAPON,
  213.         WP_MACHINEGUN,
  214. /* precache */ "",
  215. /* sounds */ ""
  216.     },
  217.  
  218. /*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  219. */
  220.     {
  221.         "weapon_grenadelauncher",
  222.         "sound/misc/w_pkup.wav",
  223.         { "models/weapons2/grenadel/grenadel.md3", 
  224.         0, 0, 0},
  225. /* icon */        "icons/iconw_grenade",
  226. /* pickup */    "Grenade Launcher",
  227.         10,
  228.         IT_WEAPON,
  229.         WP_GRENADE_LAUNCHER,
  230. /* precache */ "",
  231. /* sounds */ "sound/weapons/grenade/hgrenb1a.wav sound/weapons/grenade/hgrenb2a.wav"
  232.     },
  233.  
  234. /*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  235. */
  236.     {
  237.         "weapon_rocketlauncher",
  238.         "sound/misc/w_pkup.wav",
  239.         { "models/weapons2/rocketl/rocketl.md3", 
  240.         0, 0, 0},
  241. /* icon */        "icons/iconw_rocket",
  242. /* pickup */    "Rocket Launcher",
  243.         10,
  244.         IT_WEAPON,
  245.         WP_ROCKET_LAUNCHER,
  246. /* precache */ "",
  247. /* sounds */ ""
  248.     },
  249.  
  250. /*QUAKED weapon_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  251. */
  252.     {
  253.         "weapon_lightning", 
  254.         "sound/misc/w_pkup.wav",
  255.         { "models/weapons2/lightning/lightning.md3", 
  256.         0, 0, 0},
  257. /* icon */        "icons/iconw_lightning",
  258. /* pickup */    "Lightning Gun",
  259.         100,
  260.         IT_WEAPON,
  261.         WP_LIGHTNING,
  262. /* precache */ "",
  263. /* sounds */ ""
  264.     },
  265.  
  266. /*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  267. */
  268.     {
  269.         "weapon_railgun", 
  270.         "sound/misc/w_pkup.wav",
  271.         { "models/weapons2/railgun/railgun.md3", 
  272.         0, 0, 0},
  273. /* icon */        "icons/iconw_railgun",
  274. /* pickup */    "Railgun",
  275.         10,
  276.         IT_WEAPON,
  277.         WP_RAILGUN,
  278. /* precache */ "",
  279. /* sounds */ ""
  280.     },
  281.  
  282. /*QUAKED weapon_plasmagun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  283. */
  284.     {
  285.         "weapon_plasmagun", 
  286.         "sound/misc/w_pkup.wav",
  287.         { "models/weapons2/plasma/plasma.md3", 
  288.         0, 0, 0},
  289. /* icon */        "icons/iconw_plasma",
  290. /* pickup */    "Plasma Gun",
  291.         50,
  292.         IT_WEAPON,
  293.         WP_PLASMAGUN,
  294. /* precache */ "",
  295. /* sounds */ ""
  296.     },
  297.  
  298. /*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  299. */
  300.     {
  301.         "weapon_bfg",
  302.         "sound/misc/w_pkup.wav",
  303.         { "models/weapons2/bfg/bfg.md3", 
  304.         0, 0, 0},
  305. /* icon */        "icons/iconw_bfg",
  306. /* pickup */    "BFG10K",
  307.         20,
  308.         IT_WEAPON,
  309.         WP_BFG,
  310. /* precache */ "",
  311. /* sounds */ ""
  312.     },
  313.  
  314. /*QUAKED weapon_grapplinghook (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  315. */
  316.     {
  317.         "weapon_grapplinghook",
  318.         "sound/misc/w_pkup.wav",
  319.         { "models/weapons2/grapple/grapple.md3", 
  320.         0, 0, 0},
  321. /* icon */        "icons/iconw_grapple",
  322. /* pickup */    "Grappling Hook",
  323.         0,
  324.         IT_WEAPON,
  325.         WP_GRAPPLING_HOOK,
  326. /* precache */ "",
  327. /* sounds */ ""
  328.     },
  329.  
  330.     //
  331.     // AMMO ITEMS
  332.     //
  333.  
  334. /*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  335. */
  336.     {
  337.         "ammo_shells",
  338.         "sound/misc/am_pkup.wav",
  339.         { "models/powerups/ammo/shotgunam.md3", 
  340.         0, 0, 0},
  341. /* icon */        "icons/icona_shotgun",
  342. /* pickup */    "Shells",
  343.         10,
  344.         IT_AMMO,
  345.         WP_SHOTGUN,
  346. /* precache */ "",
  347. /* sounds */ ""
  348.     },
  349.  
  350. /*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  351. */
  352.     {
  353.         "ammo_bullets",
  354.         "sound/misc/am_pkup.wav",
  355.         { "models/powerups/ammo/machinegunam.md3", 
  356.         0, 0, 0},
  357. /* icon */        "icons/icona_machinegun",
  358. /* pickup */    "Bullets",
  359.         50,
  360.         IT_AMMO,
  361.         WP_MACHINEGUN,
  362. /* precache */ "",
  363. /* sounds */ ""
  364.     },
  365.  
  366. /*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  367. */
  368.     {
  369.         "ammo_grenades",
  370.         "sound/misc/am_pkup.wav",
  371.         { "models/powerups/ammo/grenadeam.md3", 
  372.         0, 0, 0},
  373. /* icon */        "icons/icona_grenade",
  374. /* pickup */    "Grenades",
  375.         5,
  376.         IT_AMMO,
  377.         WP_GRENADE_LAUNCHER,
  378. /* precache */ "",
  379. /* sounds */ ""
  380.     },
  381.  
  382. /*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  383. */
  384.     {
  385.         "ammo_cells",
  386.         "sound/misc/am_pkup.wav",
  387.         { "models/powerups/ammo/plasmaam.md3", 
  388.         0, 0, 0},
  389. /* icon */        "icons/icona_plasma",
  390. /* pickup */    "Cells",
  391.         30,
  392.         IT_AMMO,
  393.         WP_PLASMAGUN,
  394. /* precache */ "",
  395. /* sounds */ ""
  396.     },
  397.  
  398. /*QUAKED ammo_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  399. */
  400.     {
  401.         "ammo_lightning",
  402.         "sound/misc/am_pkup.wav",
  403.         { "models/powerups/ammo/lightningam.md3", 
  404.         0, 0, 0},
  405. /* icon */        "icons/icona_lightning",
  406. /* pickup */    "Lightning",
  407.         60,
  408.         IT_AMMO,
  409.         WP_LIGHTNING,
  410. /* precache */ "",
  411. /* sounds */ ""
  412.     },
  413.  
  414. /*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  415. */
  416.     {
  417.         "ammo_rockets",
  418.         "sound/misc/am_pkup.wav",
  419.         { "models/powerups/ammo/rocketam.md3", 
  420.         0, 0, 0},
  421. /* icon */        "icons/icona_rocket",
  422. /* pickup */    "Rockets",
  423.         5,
  424.         IT_AMMO,
  425.         WP_ROCKET_LAUNCHER,
  426. /* precache */ "",
  427. /* sounds */ ""
  428.     },
  429.  
  430. /*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  431. */
  432.     {
  433.         "ammo_slugs",
  434.         "sound/misc/am_pkup.wav",
  435.         { "models/powerups/ammo/railgunam.md3", 
  436.         0, 0, 0},
  437. /* icon */        "icons/icona_railgun",
  438. /* pickup */    "Slugs",
  439.         10,
  440.         IT_AMMO,
  441.         WP_RAILGUN,
  442. /* precache */ "",
  443. /* sounds */ ""
  444.     },
  445.  
  446. /*QUAKED ammo_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  447. */
  448.     {
  449.         "ammo_bfg",
  450.         "sound/misc/am_pkup.wav",
  451.         { "models/powerups/ammo/bfgam.md3", 
  452.         0, 0, 0},
  453. /* icon */        "icons/icona_bfg",
  454. /* pickup */    "Bfg Ammo",
  455.         15,
  456.         IT_AMMO,
  457.         WP_BFG,
  458. /* precache */ "",
  459. /* sounds */ ""
  460.     },
  461.  
  462.     //
  463.     // HOLDABLE ITEMS
  464.     //
  465. /*QUAKED holdable_teleporter (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  466. */
  467.     {
  468.         "holdable_teleporter", 
  469.         "sound/items/holdable.wav",
  470.         { "models/powerups/holdable/teleporter.md3", 
  471.         0, 0, 0},
  472. /* icon */        "icons/teleporter",
  473. /* pickup */    "Personal Teleporter",
  474.         60,
  475.         IT_HOLDABLE,
  476.         HI_TELEPORTER,
  477. /* precache */ "",
  478. /* sounds */ ""
  479.     },
  480.  
  481. /*QUAKED holdable_medkit (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  482. */
  483.     {
  484.         "holdable_medkit", 
  485.         "sound/items/holdable.wav",
  486.         { 
  487.         "models/powerups/holdable/medkit.md3", 
  488.         "models/powerups/holdable/medkit_sphere.md3",
  489.         0, 0},
  490. /* icon */        "icons/medkit",
  491. /* pickup */    "Medkit",
  492.         60,
  493.         IT_HOLDABLE,
  494.         HI_MEDKIT,
  495. /* precache */ "",
  496. /* sounds */ "sound/items/use_medkit.wav"
  497.     },
  498.  
  499.     //
  500.     // POWERUP ITEMS
  501.     //
  502. /*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  503. */
  504.     {
  505.         "item_quad", 
  506.         "sound/items/quaddamage.wav",
  507.         { "models/powerups/instant/quad.md3", 
  508.         "models/powerups/instant/quad_ring.md3",
  509.         0, 0 },
  510. /* icon */        "icons/quad",
  511. /* pickup */    "Quad Damage",
  512.         30,
  513.         IT_POWERUP,
  514.         PW_QUAD,
  515. /* precache */ "",
  516. /* sounds */ "sound/items/damage2.wav sound/items/damage3.wav"
  517.     },
  518.  
  519. /*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  520. */
  521.     {
  522.         "item_enviro",
  523.         "sound/items/protect.wav",
  524.         { "models/powerups/instant/enviro.md3", 
  525.         "models/powerups/instant/enviro_ring.md3", 
  526.         0, 0 },
  527. /* icon */        "icons/envirosuit",
  528. /* pickup */    "Battle Suit",
  529.         30,
  530.         IT_POWERUP,
  531.         PW_BATTLESUIT,
  532. /* precache */ "",
  533. /* sounds */ "sound/items/airout.wav sound/items/protect3.wav"
  534.     },
  535.  
  536. /*QUAKED item_haste (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  537. */
  538.     {
  539.         "item_haste",
  540.         "sound/items/haste.wav",
  541.         { "models/powerups/instant/haste.md3", 
  542.         "models/powerups/instant/haste_ring.md3", 
  543.         0, 0 },
  544. /* icon */        "icons/haste",
  545. /* pickup */    "Speed",
  546.         30,
  547.         IT_POWERUP,
  548.         PW_HASTE,
  549. /* precache */ "",
  550. /* sounds */ ""
  551.     },
  552.  
  553. /*QUAKED item_invis (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  554. */
  555.     {
  556.         "item_invis",
  557.         "sound/items/invisibility.wav",
  558.         { "models/powerups/instant/invis.md3", 
  559.         "models/powerups/instant/invis_ring.md3", 
  560.         0, 0 },
  561. /* icon */        "icons/invis",
  562. /* pickup */    "Invisibility",
  563.         30,
  564.         IT_POWERUP,
  565.         PW_INVIS,
  566. /* precache */ "",
  567. /* sounds */ ""
  568.     },
  569.  
  570. /*QUAKED item_regen (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  571. */
  572.     {
  573.         "item_regen",
  574.         "sound/items/regeneration.wav",
  575.         { "models/powerups/instant/regen.md3", 
  576.         "models/powerups/instant/regen_ring.md3", 
  577.         0, 0 },
  578. /* icon */        "icons/regen",
  579. /* pickup */    "Regeneration",
  580.         30,
  581.         IT_POWERUP,
  582.         PW_REGEN,
  583. /* precache */ "",
  584. /* sounds */ "sound/items/regen.wav"
  585.     },
  586.  
  587. /*QUAKED item_flight (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  588. */
  589.     {
  590.         "item_flight",
  591.         "sound/items/flight.wav",
  592.         { "models/powerups/instant/flight.md3", 
  593.         "models/powerups/instant/flight_ring.md3", 
  594.         0, 0 },
  595. /* icon */        "icons/flight",
  596. /* pickup */    "Flight",
  597.         60,
  598.         IT_POWERUP,
  599.         PW_FLIGHT,
  600. /* precache */ "",
  601. /* sounds */ "sound/items/flight.wav"
  602.     },
  603.  
  604. /*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
  605. Only in CTF games
  606. */
  607.     {
  608.         "team_CTF_redflag",
  609.         "sound/teamplay/flagtk_red.wav",
  610.         { "models/flags/r_flag.md3",
  611.         0, 0, 0 },
  612. /* icon */        "icons/iconf_red1",
  613. /* pickup */    "Red Flag",
  614.         0,
  615.         IT_TEAM,
  616.         PW_REDFLAG,
  617. /* precache */ "",
  618. /* sounds */ "sound/teamplay/flagcap_red.wav sound/teamplay/flagtk_red.wav sound/teamplay/flagret_red.wav"
  619.     },
  620.  
  621. /*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16)
  622. Only in CTF games
  623. */
  624.     {
  625.         "team_CTF_blueflag",
  626.         "sound/teamplay/flagtk_blu.wav",
  627.         { "models/flags/b_flag.md3",
  628.         0, 0, 0 },
  629. /* icon */        "icons/iconf_blu1",
  630. /* pickup */    "Blue Flag",
  631.         0,
  632.         IT_TEAM,
  633.         PW_BLUEFLAG,
  634. /* precache */ "",
  635. /* sounds */ "sound/teamplay/flagcap_blu.wav sound/teamplay/flagtk_blu.wav sound/teamplay/flagret_blu.wav"
  636.     },
  637.  
  638.     // end of list marker
  639.     {NULL}
  640. };
  641.  
  642. int        bg_numItems = sizeof(bg_itemlist) / sizeof(bg_itemlist[0]) - 1;
  643.  
  644.  
  645. /*
  646. ==============
  647. BG_FindItemForPowerup
  648. ==============
  649. */
  650. gitem_t    *BG_FindItemForPowerup( powerup_t pw ) {
  651.     int        i;
  652.  
  653.     for ( i = 0 ; i < bg_numItems ; i++ ) {
  654.         if ( (bg_itemlist[i].giType == IT_POWERUP || 
  655.                 bg_itemlist[i].giType == IT_TEAM) && 
  656.             bg_itemlist[i].giTag == pw ) {
  657.             return &bg_itemlist[i];
  658.         }
  659.     }
  660.  
  661.     return NULL;
  662. }
  663.  
  664.  
  665. /*
  666. ==============
  667. BG_FindItemForHoldable
  668. ==============
  669. */
  670. gitem_t    *BG_FindItemForHoldable( holdable_t pw ) {
  671.     int        i;
  672.  
  673.     for ( i = 0 ; i < bg_numItems ; i++ ) {
  674.         if ( bg_itemlist[i].giType == IT_HOLDABLE && bg_itemlist[i].giTag == pw ) {
  675.             return &bg_itemlist[i];
  676.         }
  677.     }
  678.  
  679.     Com_Error( ERR_DROP, "HoldableItem not found" );
  680.  
  681.     return NULL;
  682. }
  683.  
  684.  
  685. /*
  686. ===============
  687. BG_FindItemForWeapon
  688.  
  689. ===============
  690. */
  691. gitem_t    *BG_FindItemForWeapon( weapon_t weapon ) {
  692.     gitem_t    *it;
  693.     
  694.     for ( it = bg_itemlist + 1 ; it->classname ; it++) {
  695.         if ( it->giType == IT_WEAPON && it->giTag == weapon ) {
  696.             return it;
  697.         }
  698.     }
  699.  
  700.     Com_Error( ERR_DROP, "Couldn't find item for weapon %i", weapon);
  701.     return NULL;
  702. }
  703.  
  704. /*
  705. ===============
  706. BG_FindItem
  707.  
  708. ===============
  709. */
  710. gitem_t    *BG_FindItem( const char *pickupName ) {
  711.     gitem_t    *it;
  712.     
  713.     for ( it = bg_itemlist + 1 ; it->classname ; it++ ) {
  714.         if ( !Q_stricmp( it->pickup_name, pickupName ) )
  715.             return it;
  716.     }
  717.  
  718.     return NULL;
  719. }
  720.  
  721. /*
  722. ============
  723. BG_PlayerTouchesItem
  724.  
  725. Items can be picked up without actually touching their physical bounds to make
  726. grabbing them easier
  727. ============
  728. */
  729. qboolean    BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ) {
  730.     vec3_t        origin;
  731.  
  732.     BG_EvaluateTrajectory( &item->pos, atTime, origin );
  733.  
  734.     // we are ignoring ducked differences here
  735.     if ( ps->origin[0] - origin[0] > 44
  736.         || ps->origin[0] - origin[0] < -50
  737.         || ps->origin[1] - origin[1] > 36
  738.         || ps->origin[1] - origin[1] < -36
  739.         || ps->origin[2] - origin[2] > 36
  740.         || ps->origin[2] - origin[2] < -36 ) {
  741.         return qfalse;
  742.     }
  743.  
  744.     return qtrue;
  745. }
  746.  
  747.  
  748.  
  749. /*
  750. ================
  751. BG_CanItemBeGrabbed
  752.  
  753. Returns false if the item should not be picked up.
  754. This needs to be the same for client side prediction and server use.
  755. ================
  756. */
  757. qboolean    BG_CanItemBeGrabbed( const entityState_t *ent, const playerState_t *ps ) {
  758.     gitem_t    *item;
  759.  
  760.     if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) {
  761.         Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" );
  762.     }
  763.  
  764.     item = &bg_itemlist[ent->modelindex];
  765.  
  766.     switch( item->giType ) {
  767.     case IT_WEAPON:
  768.         return qtrue;    // weapons are always picked up
  769.  
  770.     case IT_AMMO:
  771.         if ( ps->ammo[ item->giTag ] >= 200 ) {
  772.             return qfalse;        // can't hold any more
  773.         }
  774.         return qtrue;
  775.  
  776.     case IT_ARMOR:
  777.         // we also clamp armor to the maxhealth for handicapping
  778.         if ( ps->stats[STAT_ARMOR] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
  779.             return qfalse;
  780.         }
  781.         return qtrue;
  782.  
  783.     case IT_HEALTH:
  784.         // small and mega healths will go over the max, otherwise
  785.         // don't pick up if already at max
  786.         if ( item->quantity == 5 || item->quantity == 100 ) {
  787.             if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
  788.                 return qfalse;
  789.             }
  790.             return qtrue;
  791.         }
  792.  
  793.         if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] ) {
  794.             return qfalse;
  795.         }
  796.         return qtrue;
  797.  
  798.     case IT_POWERUP:
  799.         return qtrue;    // powerups are always picked up
  800.  
  801.     case IT_TEAM: // team items, such as flags
  802.         // ent->modelindex2 is non-zero on items if they are dropped
  803.         // we need to know this because we can pick up our dropped flag (and return it)
  804.         // but we can't pick up our flag at base
  805.         if (ps->persistant[PERS_TEAM] == TEAM_RED) {
  806.             if (item->giTag == PW_BLUEFLAG ||
  807.                 (item->giTag == PW_REDFLAG && ent->modelindex2) ||
  808.                 (item->giTag == PW_REDFLAG && ps->powerups[PW_BLUEFLAG]))
  809.                 return qtrue;
  810.         } else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
  811.             if (item->giTag == PW_REDFLAG ||
  812.                 (item->giTag == PW_BLUEFLAG && ent->modelindex2) ||
  813.                 (item->giTag == PW_BLUEFLAG && ps->powerups[PW_REDFLAG]))
  814.                 return qtrue;
  815.         }
  816.         return qfalse;
  817.  
  818.     case IT_HOLDABLE:
  819.         // can only hold one item at a time
  820.         if ( ps->stats[STAT_HOLDABLE_ITEM] ) {
  821.             return qfalse;
  822.         }
  823.         return qtrue;
  824.  
  825.         case IT_BAD:
  826.             Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD" );
  827.     }
  828.  
  829.     return qfalse;
  830. }
  831.  
  832. //======================================================================
  833.  
  834. /*
  835. ================
  836. BG_EvaluateTrajectory
  837.  
  838. ================
  839. */
  840. void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
  841.     float        deltaTime;
  842.     float        phase;
  843.  
  844.     switch( tr->trType ) {
  845.     case TR_STATIONARY:
  846.     case TR_INTERPOLATE:
  847.         VectorCopy( tr->trBase, result );
  848.         break;
  849.     case TR_LINEAR:
  850.         deltaTime = ( atTime - tr->trTime ) * 0.001;    // milliseconds to seconds
  851.         VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  852.         break;
  853.     case TR_SINE:
  854.         deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  855.         phase = sin( deltaTime * M_PI * 2 );
  856.         VectorMA( tr->trBase, phase, tr->trDelta, result );
  857.         break;
  858.     case TR_LINEAR_STOP:
  859.         if ( atTime > tr->trTime + tr->trDuration ) {
  860.             atTime = tr->trTime + tr->trDuration;
  861.         }
  862.         deltaTime = ( atTime - tr->trTime ) * 0.001;    // milliseconds to seconds
  863.         if ( deltaTime < 0 ) {
  864.             deltaTime = 0;
  865.         }
  866.         VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  867.         break;
  868.     case TR_GRAVITY:
  869.         deltaTime = ( atTime - tr->trTime ) * 0.001;    // milliseconds to seconds
  870.         VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  871.         result[2] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime;        // FIXME: local gravity...
  872.         break;
  873.     default:
  874.         Com_Error( ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime );
  875.         break;
  876.     }
  877. }
  878.  
  879. /*
  880. ================
  881. BG_EvaluateTrajectoryDelta
  882.  
  883. For determining velocity at a given time
  884. ================
  885. */
  886. void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) {
  887.     float    deltaTime;
  888.     float    phase;
  889.  
  890.     switch( tr->trType ) {
  891.     case TR_STATIONARY:
  892.     case TR_INTERPOLATE:
  893.         VectorClear( result );
  894.         break;
  895.     case TR_LINEAR:
  896.         VectorCopy( tr->trDelta, result );
  897.         break;
  898.     case TR_SINE:
  899.         deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  900.         phase = cos( deltaTime * M_PI * 2 );    // derivative of sin = cos
  901.         phase *= 0.5;
  902.         VectorScale( tr->trDelta, phase, result );
  903.         break;
  904.     case TR_LINEAR_STOP:
  905.         if ( atTime > tr->trTime + tr->trDuration ) {
  906.             VectorClear( result );
  907.             return;
  908.         }
  909.         VectorCopy( tr->trDelta, result );
  910.         break;
  911.     case TR_GRAVITY:
  912.         deltaTime = ( atTime - tr->trTime ) * 0.001;    // milliseconds to seconds
  913.         VectorCopy( tr->trDelta, result );
  914.         result[2] -= DEFAULT_GRAVITY * deltaTime;        // FIXME: local gravity...
  915.         break;
  916.     default:
  917.         Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime );
  918.         break;
  919.     }
  920. }
  921.  
  922. /*
  923. ===============
  924. BG_AddPredictableEventToPlayerstate
  925.  
  926. Handles the sequence numbers
  927. ===============
  928. */
  929. void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) {
  930.     ps->events[ps->eventSequence & (MAX_PS_EVENTS-1)] = newEvent;
  931.     ps->eventParms[ps->eventSequence & (MAX_PS_EVENTS-1)] = eventParm;
  932.     ps->eventSequence++;
  933. }
  934.  
  935.  
  936. /*
  937. ========================
  938. BG_PlayerStateToEntityState
  939.  
  940. This is done after each set of usercmd_t on the server,
  941. and after local prediction on the client
  942. ========================
  943. */
  944. void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ) {
  945.     int        i;
  946.  
  947.     if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
  948.         s->eType = ET_INVISIBLE;
  949.     } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
  950.         s->eType = ET_INVISIBLE;
  951.     } else {
  952.         s->eType = ET_PLAYER;
  953.     }
  954.  
  955.     s->number = ps->clientNum;
  956.  
  957.     s->pos.trType = TR_INTERPOLATE;
  958.     VectorCopy( ps->origin, s->pos.trBase );
  959.     if ( snap ) {
  960.         SnapVector( s->pos.trBase );
  961.     }
  962.  
  963.     s->apos.trType = TR_INTERPOLATE;
  964.     VectorCopy( ps->viewangles, s->apos.trBase );
  965.     if ( snap ) {
  966.         SnapVector( s->apos.trBase );
  967.     }
  968.  
  969.     s->angles2[YAW] = ps->movementDir;
  970.     s->legsAnim = ps->legsAnim;
  971.     s->torsoAnim = ps->torsoAnim;
  972.     s->clientNum = ps->clientNum;        // ET_PLAYER looks here instead of at number
  973.                                         // so corpses can also reference the proper config
  974.     s->eFlags = ps->eFlags;
  975.     if ( ps->stats[STAT_HEALTH] <= 0 ) {
  976.         s->eFlags |= EF_DEAD;
  977.     } else {
  978.         s->eFlags &= ~EF_DEAD;
  979.     }
  980.  
  981.     if ( ps->externalEvent ) {
  982.         s->event = ps->externalEvent;
  983.         s->eventParm = ps->externalEventParm;
  984.     } else {
  985.         int        seq;
  986.  
  987.         seq = (ps->eventSequence-1) & (MAX_PS_EVENTS-1);
  988.         s->event = ps->events[ seq ] | ( ( ps->eventSequence & 3 ) << 8 );
  989.         s->eventParm = ps->eventParms[ seq ];
  990.     }
  991.  
  992.     s->weapon = ps->weapon;
  993.     s->groundEntityNum = ps->groundEntityNum;
  994.  
  995.     s->powerups = 0;
  996.     for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
  997.         if ( ps->powerups[ i ] ) {
  998.             s->powerups |= 1 << i;
  999.         }
  1000.     }
  1001. }
  1002.  
  1003.  
  1004.